﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using IsmsExplorer.Infrastructure.DomainBase;
using IsmsExplorer.Infrastructure.RepositoryFramework;
using System.Transactions;

namespace IsmsExplorer.Infrastructure {
    public class UnitOfWork : IUnitOfWork {
        #region Data members
        // NOTE: currently for most entities the ID is a unique id assigned by the database and uniqe per entity type.
        //       It is therefore possible to have entities with same id (but different type). As the ID is used for the
        //       hashcode, using Dictionary<> to store entities is not appropriate hence the usage of lists.
        //protected Dictionary<EntityBase, IUnitOfWorkRepository> _addedEntities = new Dictionary<EntityBase, IUnitOfWorkRepository>();
        //protected Dictionary<EntityBase, IUnitOfWorkRepository> _updatedEntities = new Dictionary<EntityBase, IUnitOfWorkRepository>();
        //protected Dictionary<EntityBase, IUnitOfWorkRepository> _deletedEntities = new Dictionary<EntityBase, IUnitOfWorkRepository>();

        protected List<Tuple<EntityBase, IUnitOfWorkRepository>> _addedEntities = new List<Tuple<EntityBase, IUnitOfWorkRepository>>();
        protected List<Tuple<EntityBase, IUnitOfWorkRepository>> _updatedEntities = new List<Tuple<EntityBase, IUnitOfWorkRepository>>();
        protected List<Tuple<EntityBase, IUnitOfWorkRepository>> _deletedEntities = new List<Tuple<EntityBase, IUnitOfWorkRepository>>();
        #endregion

        #region IUnitOfWork implementation

        public void RegisterAdded(DomainBase.EntityBase entity, RepositoryFramework.IUnitOfWorkRepository repository) {
            //this._addedEntities.Add(entity, repository);
            this._addedEntities.Add(new Tuple<EntityBase, IUnitOfWorkRepository>(entity, repository));
        }

        public void RegisterUpdated(DomainBase.EntityBase entity, RepositoryFramework.IUnitOfWorkRepository repository) {
            //this._updatedEntities.Add(entity, repository);
            this._updatedEntities.Add(new Tuple<EntityBase, IUnitOfWorkRepository>(entity, repository));
        }

        public void RegisterDeleted(DomainBase.EntityBase entity, RepositoryFramework.IUnitOfWorkRepository repository) {
            //this._deletedEntities.Add(entity, repository);
            this._deletedEntities.Add(new Tuple<EntityBase, IUnitOfWorkRepository>(entity, repository));
        }

        public void Commit() {
            using (TransactionScope scope = new TransactionScope()) {
                foreach (var tuple in _deletedEntities) {
                    tuple.Item2.PersistDeletedItem(tuple.Item1);
                }
                foreach (var tuple in _addedEntities) {
                    tuple.Item2.PersistNewItem(tuple.Item1);
                }
                foreach (var tuple in _updatedEntities) {
                    tuple.Item2.PersistUpdatedItem(tuple.Item1);
                }
                //foreach (EntityBase entity in _deletedEntities.Keys) {
                //    _deletedEntities[entity].PersistDeletedItem(entity);
                //}
                //foreach (EntityBase entity in _addedEntities.Keys) {
                //    _addedEntities[entity].PersistNewItem(entity);
                //}
                //foreach (EntityBase entity in _updatedEntities.Keys) {
                //    _updatedEntities[entity].PersistUpdatedItem(entity);
                //}

                // Commit changes!
                scope.Complete();
            }

            // If reached here, all successful, clear cache of entities.
            _deletedEntities.Clear();
            _addedEntities.Clear();
            _updatedEntities.Clear();
        }

        #endregion

    } // end public class UnitOfWork : IUnitOfWork
}
